from flask import request, jsonify, current_app, render_template, abort, g

from info import db
from info.constants import CLICK_RANK_MAX_NEWS
from info.models import News, Category, Comment, CommentLike, User
from info.utils.common import user_login_data
from info.utils.response_code import RET, error_map
from . import news_blu
#获取新闻详情
@news_blu.route('/<int:news_id>')
@user_login_data
def get_news_detail(news_id):

    # 查表获取新闻
    try:
        news = News.query.get(news_id)
    except BaseException as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg=error_map[RET.DBERR])

    if not news:
        return abort(404)
    # 浏览量
    news.clicks += 1
    # 取出数据库的新闻信息按点击量
    news_list = None  # type:list[News]
    try:
        news_list = News.query.order_by(News.clicks.desc()).limit(CLICK_RANK_MAX_NEWS).all()
    except BaseException as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg=error_map[RET.DBERR])

    user = g.user
    is_collected = False
    if user:
        # 判断用户是否收藏该新闻
        if news in user.collection_news:
            is_collected = True

    #从数据库取出所有评论
    try:
        comments = Comment.query.filter(Comment.news_id==news.id).order_by(Comment.create_time.desc()).all()
    except BaseException as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg=error_map[RET.DBERR])

    # 遍历评论表
    comment_list = []
    for comment in comments:
        # 评论模型转成字典
        comment_dict = comment.to_dict()
        # 默认不点赞
        is_comment_like = False
        # 登录 的情况下
        if user:
            #             该用户点赞的所有评论
            if comment in user.up_comments:
                # 点赞了
                is_comment_like = True
                # 改变这个评论的点赞状态
        comment_dict["is_comment_like"] = is_comment_like
        # 一个新闻多条评论
        comment_list.append(comment_dict)
    # 默认不关注
    is_follow = False
    # 登陆状态并且新闻有作者
    if user and news.user:
        # 如果新闻作者在用户的关注表中,followed用户关注了哪些人
        if news.user in user.followed:
            is_follow = True
    # 如果有g.user 转成字典赋值
    user = g.user.to_dict() if g.user else None
    return render_template("news/detail.html",news=news.to_dict(),news_list=news_list,
    user=user,is_collected=is_collected,comments=comment_list,is_follow= is_follow)

#新闻收藏
@news_blu.route('/news_collect' ,methods=['POST'])
@user_login_data
def news_collect():
    # 先判断一下用户是否存在
    user = g.user
    if not user:
        return jsonify(errno=RET.SESSIONERR,errmsg=error_map[RET.SESSIONERR])
        # 获取参数
    news_id = request.json.get("news_id")
    action = request.json.get("action")
        # 校验参数
    if not all([news_id,action]):
        return jsonify(errno=RET.PARAMERR,errmsg=error_map[RET.PARAMERR])

    # 转换类型
    try:
        news_id = int(news_id)
    except BaseException as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR,errmsg=error_map[RET.PARAMERR])
    # 判断action参数是否完整
    if action not in ["collect","cancel_collect"]:

        return jsonify(errno=RET.PARAMERR,errmsg=error_map[RET.PARAMERR])
    # 判断新闻是否存在
    try:
        news = News.query.get(news_id)
    except BaseException as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg=error_map[RET.DBERR])

    if not news:

        return jsonify(errno=RET.NODATA,errmsg=error_map[RET.NODATA])

    # 判断是收藏/取消收藏

    if action == "collect":    #收藏把新闻添加到该用户的收藏表中
        if news not in user.collection_news:

            user.collection_news.append(news)

    if action == "cancel_collect":  #取消收藏把新闻从用户收藏表中删除
        if news in user.collection_news:

            user.collection_news.remove(news)

    return jsonify(errno=RET.OK,errmsg=error_map[RET.OK])

#新闻评论
@news_blu.route('/news_comment', methods=['POST'])
@user_login_data
def news_comment():

    user = g.user
    if not user:
        return jsonify(errno=RET.SESSIONERR,errmsg=error_map[RET.SESSIONERR])
    # 获取参数
    news_id = request.json.get("news_id")
    comment_content = request.json.get("comment")
    parent_id = request.json.get("parent_id")

    # 校验参数
    if not all([news_id,comment_content]):

        return jsonify(errno=RET.PARAMERR,errmsg=error_map[RET.PARAMERR])

    # 转换类型
    try:
        news_id = int(news_id)
    except BaseException as e:
        current_app.logger.error(e)

    # 根据news_id获取新闻
    try:
        news = News.query.get(news_id)
    except BaseException as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg=error_map[RET.DBERR])
    # 判断是否有新闻
    if not news:
        return jsonify(errno=RET.NODATA,errmsg=error_map[RET.NODATA])

    # 生成评论模型
    #创建一个评论对象,就是往评论表中添加一行数据
    comment = Comment()
    comment.content = comment_content
    comment.news_id = news_id
    comment.user_id = user.id
    if parent_id:
        try:
            comment.parent_id = int(parent_id)
        except BaseException as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.PARAMERR,errmsg=error_map[RET.PARAMERR])

    db.session.add(comment)
    try:
        db.session.commit()
    except BaseException as e:
        db.session.rollback()
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg=error_map[RET.DBERR])


    return jsonify(errno=RET.OK,errmsg=error_map[RET.OK],data= comment.to_dict())

#新闻点赞
@news_blu.route('/comment_like', methods=['POST'])
@user_login_data
def comment_like():
    # 判断用户是否存在
    user = g.user
    if not user:
        return jsonify(errno=RET.SESSIONERR,errmsg=error_map[RET.SESSIONERR])
     # 获取参数

    comment_id = request.json.get("comment_id")
    action = request.json.get("action")

    # 校验参数
    if not all([comment_id,action]):

        return jsonify(errno=RET.PARAMERR,errmsg=error_map[RET.PARAMERR])

    if action not in ["add","remove"]:
        return jsonify(errno=RET.PARAMERR,errmsg=error_map[RET.PARAMERR])
    # 类型转换
    try:
        comment_id = int(comment_id)
    except BaseException as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR,errmsg=error_map[RET.PARAMERR])
    # 查询是否有该评论
    try:
        comment = Comment.query.get(comment_id)
    except BaseException as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg=error_map[RET.DBERR])

    if not comment:
        return jsonify(errno=RET.NODATA,errmsg=error_map[RET.NODATA])
    # 判断这个用户是否对该评论点赞
    try:
        ck = CommentLike.query.filter(CommentLike.comment_id==comment_id,CommentLike.user_id==user.id).first()
    except BaseException as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg=error_map[RET.DBERR])
    # 点赞时
    if action == "add":
        # 数据库没有点赞记录把点赞加进去
        if not ck:

            comment_like = CommentLike()

            comment_like.user_id = user.id
            comment_like.comment_id = comment_id

            db.session.add(comment_like)
            # 成功了点赞数加1
            comment.like_count += 1
    if action == "remove":
        # 有,删了
        if ck:
            db.session.delete(ck)
            comment.like_count -= 1
    return jsonify(errno=RET.OK,errmsg=error_map[RET.OK])


#用户关注
@news_blu.route('/followed_user' ,methods=['POST'])
@user_login_data
def followed_user():
    # 先判断一下用户是否存在
    user = g.user
    if not user:
        return jsonify(errno=RET.SESSIONERR,errmsg=error_map[RET.SESSIONERR])
        # 获取参数
    user_id = request.json.get("user_id")
    action = request.json.get("action")
        # 校验参数
    if not all([user_id,action]):
        return jsonify(errno=RET.PARAMERR,errmsg=error_map[RET.PARAMERR])

    # 转换类型
    try:
        user_id = int(user_id)
    except BaseException as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR,errmsg=error_map[RET.PARAMERR])
    # 判断action参数是否完整
    if action not in ["follow","unfollow"]:

        return jsonify(errno=RET.PARAMERR,errmsg=error_map[RET.PARAMERR])
    # 判断作者是否存在
    try:
        author = User.query.get(user_id)
    except BaseException as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg=error_map[RET.DBERR])

    if not author:

        return jsonify(errno=RET.NODATA,errmsg=error_map[RET.NODATA])

    # 判断是收藏/取消收藏

    if action == "follow":    #关注把作者添加到该用户的关注表中
        if author not in user.followed:

            user.followed.append(author)

    if action == "unfollow":  #取消关注把新闻从用户关注表中删除
        if author in user.followed:

            user.followed.remove(author)

    return jsonify(errno=RET.OK,errmsg=error_map[RET.OK])


